using LS.Editor;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public sealed class LSEditorStyle
{
    private static LSEditorStyle s_Instance = null;
    private static LSEditorStyle Instance
    {
        get
        {
            if (s_Instance == null)
            {
                s_Instance = new LSEditorStyle();
            }
            return s_Instance;
        }
    }

    public event System.Action<EditorTheme> OnEditorThemeChanged
    {
        add
        {
            Instance.m_OnEditorThemeChanged += value;
        }

        remove
        {
            Instance.m_OnEditorThemeChanged -= value;
        }
    }

    internal Contents m_GuiContents = null;
    internal Styles m_GuiStyles = null;

    public static GUIContent EditButton
    {
        get
        {
            return Instance.m_GuiContents?.editButtonContent ?? GUIContent.none;
        }
    }

    public static Color SkinnedColor => Instance.m_GuiStyles.SckinnedColor;
    public static Color TextColor => Instance.m_GuiStyles.TextColor;
    public static Color TextDisactiveColor => Instance.m_GuiStyles.TextDisactiveColor;
    public static Color BackgroundBasisColor => Instance.m_GuiStyles.BackgroundBasisColor;
    public static Color BackgroundOverlayerColor => Instance.m_GuiStyles.BackgroundOverlayerColor;
    public static Color BackgroundOverlayerDarkColor => Instance.m_GuiStyles.BackgroundOverlayerDarkColor;
    public static Color Line => Instance.m_GuiStyles.Line;
    public static GUILayoutOption DefaultGuiHeight => Instance.m_GuiStyles.DefaultGuiHeight;
    public static GUILayoutOption DefaultGuiWidth => Instance.m_GuiStyles.DefaultGuiWidth;
    public static GUILayoutOption HorizontalSplitLineHeight => Instance.m_GuiStyles.HorizontalSplitLineHeight;
    public static GUILayoutOption VerticalSplitLineWidth => Instance.m_GuiStyles.VerticalSplitLineWidth;

    private EditorTheme m_EditorTheme = EditorTheme.Unset;
    private System.Action<EditorTheme> m_OnEditorThemeChanged;

    public LSEditorStyle()
    {
        Init();
        EditorApplication.update += Update;
    }

    ~LSEditorStyle()
    {
        Release();
    }

    internal void Init()
    {
        Update();
    }

    internal void Release()
    {
        EditorApplication.update -= Update;
    }

    public void Update()
    {
        if (EditorGUIUtility.isProSkin)
            SetEditorTheme(EditorTheme.UnityDark);
        else
            SetEditorTheme(EditorTheme.UnityLight);
    }

    private EditorTheme GetUsedTheme()
    {
        return m_EditorTheme == EditorTheme.Unset ? EditorTheme.UnityLight : m_EditorTheme;
    }

    private void SetEditorTheme(EditorTheme theme)
    {
        if (m_EditorTheme == theme) return;

        m_EditorTheme = theme;
        UpdateContents(GetUsedTheme());
        UpdateStyles(GetUsedTheme());
        m_OnEditorThemeChanged?.Invoke(m_EditorTheme);
    }

    private void UpdateContents(EditorTheme theme)
    {
        if (m_GuiContents == null)
            m_GuiContents = new Contents();

        string iconRootPath = $"{LSPathEditor.LSPluginsEditorAssetRootPath}/Icon/Theme_{m_EditorTheme.ToString()}";
        m_GuiContents.Update(iconRootPath);
    }

    private void UpdateStyles(EditorTheme theme)
    {
        if (theme == EditorTheme.UnityDark)
            m_GuiStyles = new LSStyle_Dark();
        else
            m_GuiStyles = new LSStyle_Light();
    }

    public enum EditorTheme
    {
        Unset,
        UnityLight,
        UnityDark
    }

    internal class Contents
    {
        public GUIContent editButtonContent;
        public Contents() { }

        public void Update(string iconsRootPath)
        {
            UpdateEditButtonContent(iconsRootPath);
        }

        private void UpdateEditButtonContent(string assetRootPath)
        {
            string filePath = $"{assetRootPath}/edit.png";

            if (editButtonContent == null)
                editButtonContent = new GUIContent();

            editButtonContent.image = AssetDatabase.LoadAssetAtPath<Texture2D>(filePath);
        }
    }

    internal abstract class Styles
    {
        public abstract Color SckinnedColor { get; }
        public abstract Color TextColor { get; }
        public abstract Color TextDisactiveColor { get; }
        public abstract Color BackgroundBasisColor { get; }
        public abstract Color BackgroundOverlayerColor { get; }
        public abstract Color BackgroundOverlayerDarkColor { get; }
        public abstract Color Line { get; }
        public virtual GUILayoutOption DefaultGuiHeight { get; } = GUILayout.Height(20);
        public virtual GUILayoutOption DefaultGuiWidth { get; } = GUILayout.Width(100);
        public virtual GUILayoutOption HorizontalSplitLineHeight { get; } = GUILayout.Height(1);
        public virtual GUILayoutOption VerticalSplitLineWidth { get; } = GUILayout.Width(1);

    }

    internal class LSStyle_Dark : Styles
    {

        private Color m_TextColor = new Color(200f / 255f, 200f / 255, 200 / 255, 1f);
        private Color m_TextDisactiveColor = new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.39f);
        private Color m_BackgroundBasisColor = new Color(55f / 255f, 55f / 255f, 55f / 255f, 1f);
        private Color m_BackgroundOverlayerColor = new Color(80f / 255f, 80f / 255f, 80f / 255f, 0.39f);
        private Color m_BackgroundOverlayerDarkColor = new Color(25f / 255f, 25f / 255f, 25f / 255f, 0.39f);
        private Color m_Line = new Color(95f / 255f, 95f / 255f, 95f / 255f, 1f);
        private Color m_SckinnedColor = new Color(0.12f, 0.12f, 0.12f, 1.333f);

        public override Color TextColor => m_TextColor;

        public override Color TextDisactiveColor => m_TextDisactiveColor;

        public override Color BackgroundBasisColor => m_BackgroundBasisColor;

        public override Color BackgroundOverlayerColor => m_BackgroundOverlayerColor;

        public override Color BackgroundOverlayerDarkColor => m_BackgroundOverlayerDarkColor;

        public override Color Line => m_Line;

        public override Color SckinnedColor => m_SckinnedColor;
    }

    internal class LSStyle_Light : Styles
    {
        private Color m_TextColor = new Color(200f / 255f, 200f / 255, 200 / 255, 1f);
        private Color m_TextDisactiveColor = new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.39f);
        private Color m_BackgroundBasisColor = new Color(200f / 255f, 200f / 255f, 200f / 255f, 1f);
        private Color m_BackgroundOverlayerColor = new Color(225f / 255f, 225f / 255f, 225f / 255f, 0.39f);
        private Color m_BackgroundOverlayerDarkColor = new Color(175f / 255f, 175f / 255f, 175f / 255f, 0.39f);
        private Color m_Line = new Color(150f / 255f, 150f / 255f, 150f / 255f, 1f);
        private Color m_SckinnedColor = new Color(0.12f, 0.12f, 0.12f, 1.333f);

        public override Color TextColor => m_TextColor;

        public override Color TextDisactiveColor => m_TextDisactiveColor;

        public override Color BackgroundBasisColor => m_BackgroundBasisColor;

        public override Color BackgroundOverlayerColor => m_BackgroundOverlayerColor;

        public override Color BackgroundOverlayerDarkColor => m_BackgroundOverlayerDarkColor;

        public override Color Line => m_Line;

        public override Color SckinnedColor => m_SckinnedColor;
    }
}
